import 'package:cached_network_image/cached_network_image.dart';
import 'package:family_expense/features/account_user/services/user_service.dart';
import 'package:family_expense/features/account_user/widgets/reset_login_password.dart';
import 'package:family_expense/features/account_user/widgets/update_account_group_user.dart';
import 'package:family_expense/features/account_user/widgets/user_basic_info.dart';
import 'package:family_expense/features/account_user/widgets/user_shared.dart';
import 'package:family_expense/shared/widgets/action_log.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

class AccountGroupUserDetails extends StatefulWidget {
  const AccountGroupUserDetails(this.id, {super.key});

  final String id;

  @override
  State<AccountGroupUserDetails> createState() =>
      _AccountGroupUserDetailsState();
}

class _AccountGroupUserDetailsState extends State<AccountGroupUserDetails> {
  final _appBarHeight = 200.0;
  final UserService _userService = UserService();

  bool _dataUpdated = false;

  // User info retrieves from server by id.
  User? _user;

  // Current user info loads from local.
  User? _currentUser;

  @override
  void initState() {
    super.initState();

    _getCurrentUser();
    _queryDetails();
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: _onPopInvokedWithResult,
      child: Scaffold(body: _buildBody()),
    );
  }

  /// Builds app bar.
  Widget _buildAppBar() {
    return SliverAppBar(
      expandedHeight: _appBarHeight,
      pinned: true,
      flexibleSpace: FlexibleSpaceBar(
        // Displays user full name or username.
        title: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              _user!.fullName!,
              overflow: TextOverflow.ellipsis,
              style: TextStyle(
                color: calculateContrastingColor(
                  Theme.of(context).appBarTheme.backgroundColor!,
                ),
              ),
            ),
            if (_user!.isAccountGroupCreator!)
              Text(
                '账户组注册人',
                style: TextStyle(
                  fontSize: 8.0,
                  color: calculateContrastingColor(
                    Theme.of(context).appBarTheme.backgroundColor!,
                  ),
                ),
              ),
          ],
        ),
        background: Stack(
          fit: StackFit.expand,
          children: [
            // Displays user avatar.
            Hero(
              tag: _user!.id!,
              transitionOnUserGestures: true,
              child: CachedNetworkImage(
                imageUrl: _user!.avatarUrl!,
                fit: BoxFit.cover,
                height: _appBarHeight,
              ),
            ),
            // This gradient ensures that the toolbar icons are distinct
            // against the background image.
            const DecoratedBox(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment(0.0, -1.0),
                  end: Alignment(0.0, -0.4),
                  colors: <Color>[Color(0x60000000), Color(0x00000000)],
                ),
              ),
            ),
          ],
        ),
      ),
      actions: _buildActions(),
    );
  }

  List<Widget> _buildActions() {
    Widget action = Container();

    // Shows menu to group admin ONLY.
    // Group admin can update own password and info.
    // Group admin can update the other users role setting except group creator.
    if (_currentUser?.isAccountGroupAdmin == true &&
        ((_currentUser?.id != _user?.id &&
                _user?.isAccountGroupCreator != true) ||
            _currentUser?.id == _user?.id)) {
      action = PopupMenuButton(
        icon: const Icon(Icons.more_vert_rounded),
        itemBuilder: (BuildContext context) => <PopupMenuItem>[
          if (_currentUser?.id == _user!.id)
            PopupMenuItem(
              child: ListTile(
                leading: Icon(MdiIcons.lockReset),
                title: const Text('修改密码'),
                onTap: () {
                  // Closes opened bottom sheet.
                  NavigatorHelper.pop(context);

                  NavigatorHelper.push(context, const ResetLoginPassword());
                },
              ),
            ),
          PopupMenuItem(
            child: ListTile(
              leading: Icon(MdiIcons.accountEdit),
              title: Text(_currentUser?.id == _user!.id ? '修改资料' : '修改角色'),
              onTap: () {
                // Closes opened bottom sheet.
                NavigatorHelper.pop(context);

                _gotoUpdateView();
              },
            ),
          ),
        ],
      );
    }

    return [action];
  }

  // Builds main body.
  Widget _buildBody() {
    return _user != null
        ? CustomScrollView(
            slivers: <Widget>[_buildAppBar(), _buildUserDetailList()],
          )
        : const MyPageTopCenterLoadingIndicator(
            padding: EdgeInsets.only(top: 50.0),
          );
  }

  /// Generates the user detail item list.
  Widget _buildUserDetailList() {
    return SliverList(
      delegate: SliverChildListDelegate(<Widget>[
        const ListCaption('基本信息'),
        ListTile(
          title: const Text('用户名'),
          trailing: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(_user!.username!.formatMobilePhoneNumber()),
              InkWell(
                child: const Icon(Icons.phone_android),
                onTap: () => makePhoneCall(_user!.username!),
              ),
            ],
          ),
        ),
        ListTile(
          title: const Text('状态'),
          trailing: UserEnableChip(_user!.enabled!),
        ),
        ListTile(
          title: const Text('角色'),
          trailing: Wrap(
            spacing: 8.0,
            runSpacing: 4.0,
            children: UserShared.buildUserdRoleChips(_user!),
          ),
        ),
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const ListCaption('描述'),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 15.0),
              child: Text(
                _user!.description ?? '[没有任何描述]',
                style: const TextStyle(color: Colors.black54),
              ),
            ),
          ],
        ),
        const Divider(),
        const ListCaption('操作记录'),
        ActionLogView(_user!),
        const SizedBox(height: 20.0),
      ]),
    );
  }

  /// Gets current authenticated user.
  Future<void> _getCurrentUser() async {
    final user = await AuthStateService.instance.currentUser;

    if (mounted) {
      setState(() => _currentUser = user!);
    }
  }

  /// Loads user details from server by id.
  Future<void> _queryDetails() async {
    final res = await _userService.queryDetails(widget.id);

    if (mounted) {
      setState(() => _user = res);
    }
  }

  /// Goes to detail update view.
  Future<void> _gotoUpdateView() async {
    var dataUpdated = false;

    if (_currentUser!.id == _user!.id) {
      // Current user needs to edit own info in [UserBasicInfo].
      // This is prevent to compromise user's role, status by accident.
      // Something like user removes own admin role or disables the account.
      //
      // Passing [_currentUser] as argument instead of [_user] due to the [_currentUser] contains [isAccountGroupAdmin] property value.
      // [_user] does not contain such property because this is only used by current user.
      //
      // Passing [_currentUser] instead of loading it in [UserBasicInfo] because [Hero] widget does not work with [setState] method.
      final returnUser = await NavigatorHelper.push<User>(
        context,
        UserBasicInfo(_currentUser!),
      );

      // Checks if the return user has been updated.
      dataUpdated = returnUser?.equals(_currentUser) == false;

      // If user updated own info then need to reload it.
      // This is for [UserBasicInfo] usage as route argument.
      if (dataUpdated) {
        // Returns from navigation would cause re-build. That's why [setState] is not needed.
        _currentUser = (await AuthStateService.instance.currentUser)!;
      }
    } else {
      // Current user can update other user info.
      // Takes current result that if the data has been updated.
      dataUpdated =
          await NavigatorHelper.push<bool>(
            context,
            UpdateAccountGroupUser(_user!),
          ) ??
          false;
    }

    // Only when current result indicates the data has been changed then we need to refresh the data.
    if (dataUpdated) {
      // We only need to set [_dataUpdated] as true when [dataUpdated] is true.
      //
      // - When user chaged one item then [dataUpdated] is true and [_dataUpdated] is true.
      // - When user goes to edit view and gets back without any change, then [dataUpdated] is false.
      // But we still need to notify last page that some items have been changed.
      //
      // That's why we cannnot set [_dataUpdated] to false when [dataUpdated] is false.
      _dataUpdated = true;

      // This action for display the loading icon.
      if (mounted) {
        setState(() => _user = null);
      }

      // Loads user details from server by id to update the UI.
      final res = await _userService.queryDetails(widget.id);

      if (mounted) {
        setState(() => _user = res);
      }
    }
  }

  void _onPopInvokedWithResult(bool didPop, dynamic result) {
    if (didPop) {
      return;
    }

    NavigatorHelper.pop(context, _dataUpdated);
  }
}
